package aupdg.data;

import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import edu.uci.ics.jung.graph.util.EdgeType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Defines a customized graph to represent an LDG graphically.
 *
 * @param <Node>
 * @param <Edge>
 * @author AA and CJ
 */
public class DirectedGraphCustom<Node, Edge> extends DirectedSparseMultigraph {

    private List<Object> edgesKeys;
    private List<Boolean> isEdgeTypeData;
    Map<String, Node> nodes;
    Map<String, Edge> edges;

    /**
     * Constructor.
     */
    public DirectedGraphCustom() {
        super();
        edgesKeys = new ArrayList<>();
        isEdgeTypeData = new ArrayList<>();
        nodes = new HashMap<>();
        edges = new HashMap<>();
    }

    /**
     * Adds an edge into the graph.
     *
     * @param e
     * @param v1
     * @param v2
     * @param et
     * @param isDataEdge
     */
    public void addEdge(Object e, Object v1, Object v2, EdgeType et, Boolean isDataEdge) {
        edgesKeys.add(e);
        isEdgeTypeData.add(isDataEdge);
        super.addEdge(e, v1, v2, et);
        //quitar comment cuando se modifique directed graph para que los labels sean unicos
        //addEdgeToMap(e.toString(), ldgEdge); 
    }

    /**
     * Adds a node (vertex) into the graph.
     *
     * @param v
     * @param ldgNode
     */
    public void addVertex(Object v, Node ldgNode) {
        super.addVertex(v);
        addNodeToMap(v.toString(), ldgNode);
    }

    /**
     * Given an edge the method returns true if its type is data dependence
     * edge. It return false otherwise.
     *
     * @param e
     * @return
     */
    public Boolean isDataEdge(Edge e) {
        for (int i = 0; i < edgesKeys.size(); i++) {
            if (edgesKeys.get(i).equals(e)) {
                return isEdgeTypeData.get(i);
            }
        }
        return false;
    }

    /**
     * Adds LDG Node and label to the inner nodes map.
     *
     * @param ldgNode
     * @param nodeLabel
     */
    public void addNodeToMap(String nodeLabel, Node ldgNode) {
        nodes.put(nodeLabel, ldgNode);
    }

    /**
     * Adds LDG Edge and label to the inner edges map.
     *
     * @param ldgEdge
     * @param edgeLabel
     */
    public void addEdgeToMap(String edgeLabel, Edge ldgEdge) {
        edges.put(edgeLabel, ldgEdge);
    }

    /**
     * Returns an LDG node that corresponds to the label in DirectedGraph.
     *
     * @param label
     * @return
     */
    public Node getNodeFromLabel(String label) {
        return nodes.get(label);
    }

    /**
     * Returns an LDG edge that corresponds to the label in DirectedGraph.
     *
     * @param label
     * @return
     */
    public Edge getEdgeFromLabel(String label) {
        return edges.get(label);
    }
}
